import tkinter as tk
from tkinter import ttk, messagebox, scrolledtext, filedialog, font
import itertools
import os
import json
from datetime import datetime
from PIL import Image, ImageDraw, ImageFont
import requests
import random
import time

class Lottery9FromN:
    def __init__(self, root):
        # 初始化主窗口
        self.root = root
        self.root.title("胜负彩任9组合生成器")
        self.root.geometry("1200x900")
        self.root.minsize(1000, 800)

        # 设置样式
        self.style = ttk.Style()
        self.style.configure("TButton", font=("SimHei", 10))
        self.style.configure("TLabel", font=("SimHei", 10))

        # 数据链接设置
        self.data_url = tk.StringVar(value="https://webapi.sporttery.cn/gateway/lottery/getFootBallMatchV1.qry?param=90,0&lotteryDrawNum=&sellStatus=0&termLimits=10")

        # 数据初始化
        self.matches = []
        self.match_choices = {}  # 存储格式: {match_id: {"3": False, "1": False, "0": False, "frames": {...}, "labels": {...}}}
        self.generated_combinations = []

        # 缓存选中的场次数量（减少重复计算）
        self.selected_count_cache = 0
        self.avg_choices_cache = 0

        # 创建界面
        self.create_widgets()

        # 初始加载数据
        self.refresh_data()

    def _init_match_data(self):
        """从API链接获取数据，失败则使用默认数据"""
        try:
            url = self.data_url.get().strip()
            if not url:
                raise Exception("数据链接为空，请输入有效链接")

            headers = {
                "User-Agent": random.choice([
                    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36",
                    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.5 Safari/605.1.15"
                ]),
                "Accept": "application/json, text/javascript, */*; q=0.01",
                "X-Requested-With": "XMLHttpRequest"
            }

            # 发送请求（带重试机制）
            response = None
            for _ in range(3):
                try:
                    time.sleep(random.uniform(0.5, 1.5))
                    response = requests.get(url, headers=headers, timeout=10)
                    if response.status_code == 200:
                        break
                except Exception as e:
                    print(f"请求失败: {e}")
                    continue

            if not response or response.status_code != 200:
                raise Exception(f"请求失败，状态码: {response.status_code if response else '无响应'}")

            # 解析JSON数据
            try:
                json_data = response.json()
            except Exception as e:
                raise Exception(f"解析JSON失败: {str(e)}")

            if not json_data.get("success", False):
                raise Exception(f"API返回错误: {json_data.get('errorMessage', '未知错误')}")

            # 获取比赛列表
            sfc_match = json_data.get("value", {}).get("sfcMatch", {})
            match_list = sfc_match.get("matchList", [])

            if not match_list:
                raise Exception("API中未包含比赛数据")

            # 提取前14场比赛数据
            matches = []
            for match in match_list[:14]:
                try:
                    match_num = match.get("matchNum", len(matches) + 1)
                    league = match.get("matchName", "未知联赛")

                    # 处理时间格式
                    start_time = match.get("startTime", "")
                    if len(start_time) >= 16:
                        date_part = start_time[5:10]
                        time_part = start_time[11:16]
                        match_time = f"{date_part} {time_part}"
                    else:
                        match_time = start_time or "00:00"

                    # 主客场队名和赔率
                    home_team = match.get("masterTeamName", f"主队{match_num}")
                    away_team = match.get("guestTeamName", f"客队{match_num}")
                    odds3 = float(match.get("h", 1.5 + random.random())) if match.get("h") else round(1.5 + random.random(), 2)
                    odds1 = float(match.get("d", 3.5 + random.random())) if match.get("d") else round(3.5 + random.random(), 2)
                    odds0 = float(match.get("a", 5.5 + random.random() * 2)) if match.get("a") else round(5.5 + random.random() * 2, 2)

                    matches.append({
                        "id": match_num,
                        "league": league,
                        "time": match_time,
                        "home": home_team,
                        "away": away_team,
                        "odds3": round(odds3, 2),
                        "odds1": round(odds1, 2),
                        "odds0": round(odds0, 2)
                    })
                except Exception as e:
                    current_id = len(matches) + 1
                    print(f"解析第{current_id}场比赛失败: {e}")
                    matches.append(self._get_default_single_match(current_id))

            # 确保有14场数据
            while len(matches) < 14:
                matches.append(self._get_default_single_match(len(matches) + 1))

            return matches[:14]

        except Exception as e:
            print(f"获取数据失败: {e}")
            return self._get_default_match_data()

    def _get_default_single_match(self, idx):
        """单场默认数据"""
        return {
            "id": idx,
            "league": f"联赛{idx}",
            "time": f"08-{str(idx+10).zfill(2)} 20:00",
            "home": f"主队{idx}",
            "away": f"客队{idx}",
            "odds3": round(1.2 + random.random(), 2),
            "odds1": round(3.0 + random.random(), 2),
            "odds0": round(4.0 + random.random() * 3, 2)
        }

    def _get_default_match_data(self):
        """完整默认数据"""
        return [self._get_default_single_match(i) for i in range(1, 15)]

    def create_widgets(self):
        # 主容器
        main_container = tk.Frame(self.root, padx=10, pady=10)
        main_container.pack(fill=tk.BOTH, expand=True)

        # 顶部信息栏
        top_frame = tk.Frame(main_container, bg="#f5f5f5", relief=tk.RAISED, bd=1)
        top_frame.pack(fill=tk.X, pady=(0, 10))
        top_frame.grid_columnconfigure(1, weight=1)

        # 数据链接输入区
        tk.Label(top_frame, text="数据链接:", bg="#f5f5f5", font=("SimHei", 10, "bold")).grid(
            row=0, column=0, padx=10, pady=8, sticky="w")

        url_entry = tk.Entry(top_frame, textvariable=self.data_url, font=("SimHei", 10))
        url_entry.grid(row=0, column=1, padx=5, pady=8, sticky="ew")

        tk.Button(top_frame, text="应用链接", command=self.apply_url,
                  bg="#673ab7", fg="white", padx=10).grid(
            row=0, column=2, padx=5, pady=8)

        # 期号和统计信息
        info_frame = tk.Frame(top_frame, bg="#f5f5f5")
        info_frame.grid(row=1, column=0, columnspan=3, sticky="ew", padx=10, pady=(0, 8))
        info_frame.grid_columnconfigure(1, weight=1)

        # 期号信息
        self.issue_var = tk.StringVar(value=f"第{datetime.now().strftime('%Y%m%d')}期 胜负彩 任9")
        tk.Label(info_frame, textvariable=self.issue_var, bg="#f5f5f5",
                 font=("SimHei", 12, "bold")).grid(row=0, column=0, sticky="w")

        # 选择统计
        self.selection_stats = tk.StringVar(value="已选择场次: 0 | 可生成组合数: 0 | 预计总注数: 0")
        tk.Label(info_frame, textvariable=self.selection_stats, bg="#f5f5f5",
                 font=("SimHei", 10)).grid(row=0, column=1, sticky="e")

        # 操作按钮区
        btn_frame = tk.Frame(top_frame, bg="#f5f5f5")
        btn_frame.grid(row=1, column=2, padx=10, pady=(0, 8), sticky="e")

        buttons = [
            ("刷新数据", self.refresh_data, "#9C27B0"),
            ("生成9场组合", self.generate_combinations, "#4CAF50"),
            ("导出组合", self.export_combinations, "#2196F3"),
            ("导出组合图片", self.export_combinations_as_images, "#FF9800"),
            ("清空选择", self.clear_all, "#f44336")
        ]

        for text, cmd, color in buttons:
            tk.Button(btn_frame, text=text, command=cmd,
                      bg=color, fg="white", padx=10, pady=2).pack(side=tk.LEFT, padx=5)

        # 主内容区 - 左右分栏
        content_frame = tk.Frame(main_container)
        content_frame.pack(fill=tk.BOTH, expand=True)

        # 左侧比赛列表区域
        left_frame = tk.LabelFrame(content_frame, text="比赛列表", font=("SimHei", 10, "bold"), bd=2, relief=tk.GROOVE)
        left_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=(0, 5))

        # 比赛列表标题行 - 移除对阵列
        header_frame = tk.Frame(left_frame, bg="#2c3e50")
        header_frame.pack(fill=tk.X, padx=5, pady=5)

        # 标题列 - 移除对阵列，调整宽度
        headers = ["序号", "联赛", "时间", "胜(主)", "平", "负(客)"]
        widths = [6, 12, 12, 20, 15, 20]

        for i, (header, width) in enumerate(zip(headers, widths)):
            tk.Label(header_frame, text=header, bg="#34495e", fg="white", width=width,
                     borderwidth=1, relief="solid", justify=tk.CENTER, font=("SimHei", 10, "bold")).grid(
                row=0, column=i, sticky="nsew", padx=1, pady=1)

        # 比赛列表区域（带滚动条）
        list_frame = tk.Frame(left_frame)
        list_frame.pack(fill=tk.BOTH, expand=True, padx=5, pady=(0, 5))

        canvas = tk.Canvas(list_frame)
        scrollbar = ttk.Scrollbar(list_frame, orient="vertical", command=canvas.yview)
        self.match_list_frame = ttk.Frame(canvas)

        self.match_list_frame.bind(
            "<Configure>",
            lambda e: canvas.configure(scrollregion=canvas.bbox("all"))
        )

        canvas.create_window((0, 0), window=self.match_list_frame, anchor="nw")
        canvas.configure(yscrollcommand=scrollbar.set)

        canvas.pack(side="left", fill="both", expand=True)
        scrollbar.pack(side="right", fill="y")

        # 右侧组合结果区域
        right_frame = tk.LabelFrame(content_frame, text="组合结果", font=("SimHei", 10, "bold"), bd=2, relief=tk.GROOVE)
        right_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True, padx=(5, 0))

        # 组合统计信息
        stats_frame = tk.Frame(right_frame, bg="#ecf0f1", relief=tk.SUNKEN, bd=1)
        stats_frame.pack(fill=tk.X, padx=5, pady=5)

        self.total_stats_var = tk.StringVar(value="总组合数: 0 | 总注数: 0 | 总金额: 0元")
        tk.Label(stats_frame, textvariable=self.total_stats_var, bg="#ecf0f1",
                 font=("SimHei", 10, "bold"), fg="#c0392b").pack(side=tk.LEFT, padx=10, pady=5)

        # 组合列表（带滚动条）
        combo_frame = tk.Frame(right_frame)
        combo_frame.pack(fill=tk.BOTH, expand=True, padx=5, pady=(0, 5))

        self.combo_text = scrolledtext.ScrolledText(combo_frame, wrap=tk.WORD, font=("SimHei", 10), bd=1, relief=tk.SUNKEN)
        self.combo_text.pack(fill=tk.BOTH, expand=True)
        self.combo_text.config(state=tk.DISABLED)

    def init_match_list(self):
        """初始化比赛列表 - 移除对阵列，优化点击区域"""
        # 清空现有内容
        for widget in self.match_list_frame.winfo_children():
            widget.destroy()

        # 确保有数据
        if not self.matches:
            return

        # 为每场比赛创建UI元素
        for idx, match in enumerate(self.matches):
            # 交替行背景色
            bg_color = "#ffffff" if idx % 2 == 0 else "#f0f7ff"
            row_frame = tk.Frame(self.match_list_frame, bg=bg_color, height=80, bd=1, relief=tk.RAISED)
            row_frame.pack(fill=tk.X, pady=1)
            row_frame.pack_propagate(False)

            # 初始化选择状态（预存标签引用）
            self.match_choices[match["id"]] = {
                "3": False,
                "1": False,
                "0": False,
                "frames": {},  # 存储框架引用
                "labels": {}   # 存储标签引用
            }

            # 序号
            tk.Label(row_frame, text=str(match["id"]), bg=bg_color, width=6,
                     borderwidth=0, font=("SimHei", 10, "bold")).grid(row=0, column=0, sticky="nsew", padx=1, pady=1)

            # 联赛
            tk.Label(row_frame, text=match["league"], bg=bg_color, width=12,
                     borderwidth=0).grid(row=0, column=1, sticky="nsew", padx=1, pady=1)

            # 时间
            tk.Label(row_frame, text=match["time"], bg=bg_color, width=12,
                     borderwidth=0).grid(row=0, column=2, sticky="nsew", padx=1, pady=1)

            # 胜（3）- 扩大点击区域，确保整个格子可点击
            win_frame = tk.Frame(row_frame, bg="#ffebee", bd=2, relief=tk.RAISED)
            win_frame.grid(row=0, column=3, sticky="nsew", padx=1, pady=1)
            # 绑定点击事件
            win_frame.bind("<Button-1>", lambda e, mid=match["id"], res="3": self.toggle_selection(mid, res))

            # 存储标签引用
            win_label1 = tk.Label(win_frame, text=match["home"], bg="#ffebee", font=("SimHei", 10, "bold"))
            win_label1.pack(side=tk.TOP, pady=5)
            # 防止标签吸收点击事件
            win_label1.bind("<Button-1>", lambda e, mid=match["id"], res="3": self.toggle_selection(mid, res))

            win_label2 = tk.Label(win_frame, text=f"赔率: {match['odds3']}", bg="#ffebee", font=("SimHei", 9))
            win_label2.pack(side=tk.TOP)
            win_label2.bind("<Button-1>", lambda e, mid=match["id"], res="3": self.toggle_selection(mid, res))

            self.match_choices[match["id"]]["frames"]["3"] = win_frame
            self.match_choices[match["id"]]["labels"]["3"] = [win_label1, win_label2]

            # 平（1）- 扩大点击区域
            draw_frame = tk.Frame(row_frame, bg="#fff8e1", bd=2, relief=tk.RAISED)
            draw_frame.grid(row=0, column=4, sticky="nsew", padx=1, pady=1)
            draw_frame.bind("<Button-1>", lambda e, mid=match["id"], res="1": self.toggle_selection(mid, res))

            draw_label1 = tk.Label(draw_frame, text="平", bg="#fff8e1", font=("SimHei", 10, "bold"))
            draw_label1.pack(side=tk.TOP, pady=5)
            draw_label1.bind("<Button-1>", lambda e, mid=match["id"], res="1": self.toggle_selection(mid, res))

            draw_label2 = tk.Label(draw_frame, text=f"赔率: {match['odds1']}", bg="#fff8e1", font=("SimHei", 9))
            draw_label2.pack(side=tk.TOP)
            draw_label2.bind("<Button-1>", lambda e, mid=match["id"], res="1": self.toggle_selection(mid, res))

            self.match_choices[match["id"]]["frames"]["1"] = draw_frame
            self.match_choices[match["id"]]["labels"]["1"] = [draw_label1, draw_label2]

            # 负（0）- 扩大点击区域
            lose_frame = tk.Frame(row_frame, bg="#e8f5e9", bd=2, relief=tk.RAISED)
            lose_frame.grid(row=0, column=5, sticky="nsew", padx=1, pady=1)
            lose_frame.bind("<Button-1>", lambda e, mid=match["id"], res="0": self.toggle_selection(mid, res))

            lose_label1 = tk.Label(lose_frame, text=match["away"], bg="#e8f5e9", font=("SimHei", 10, "bold"))
            lose_label1.pack(side=tk.TOP, pady=5)
            lose_label1.bind("<Button-1>", lambda e, mid=match["id"], res="0": self.toggle_selection(mid, res))

            lose_label2 = tk.Label(lose_frame, text=f"赔率: {match['odds0']}", bg="#e8f5e9", font=("SimHei", 9))
            lose_label2.pack(side=tk.TOP)
            lose_label2.bind("<Button-1>", lambda e, mid=match["id"], res="0": self.toggle_selection(mid, res))

            self.match_choices[match["id"]]["frames"]["0"] = lose_frame
            self.match_choices[match["id"]]["labels"]["0"] = [lose_label1, lose_label2]

            # 配置列权重，让选择格子更宽
            for i in range(6):
                weight = 1 if i < 3 else 3  # 选择列权重更大
                row_frame.grid_columnconfigure(i, weight=weight)

    def toggle_selection(self, match_id, result):
        """切换选中状态 - 移除事件参数，解决传播错误"""
        # 切换状态
        current_state = self.match_choices[match_id][result]
        new_state = not current_state
        self.match_choices[match_id][result] = new_state

        # 使用预存的框架和标签引用
        frame = self.match_choices[match_id]["frames"][result]
        labels = self.match_choices[match_id]["labels"][result]

        # 更新UI样式
        if new_state:
            # 选中状态
            if result == "3":
                frame.config(bg="#e74c3c", relief=tk.SUNKEN)
                for label in labels:
                    label.config(bg="#e74c3c", fg="white")
            elif result == "1":
                frame.config(bg="#f39c12", relief=tk.SUNKEN)
                for label in labels:
                    label.config(bg="#f39c12", fg="white")
            else:
                frame.config(bg="#27ae60", relief=tk.SUNKEN)
                for label in labels:
                    label.config(bg="#27ae60", fg="white")
        else:
            # 未选中状态
            if result == "3":
                frame.config(bg="#ffebee", relief=tk.RAISED)
                for label in labels:
                    label.config(bg="#ffebee", fg="black")
            elif result == "1":
                frame.config(bg="#fff8e1", relief=tk.RAISED)
                for label in labels:
                    label.config(bg="#fff8e1", fg="black")
            else:
                frame.config(bg="#e8f5e9", relief=tk.RAISED)
                for label in labels:
                    label.config(bg="#e8f5e9", fg="black")

        # 延迟更新统计信息
        self.root.after(30, self.update_selection_stats)

    def get_selected_matches(self):
        """获取所有至少选择了一个胜平负选项的场次"""
        selected = []
        total_choices = 0
        for m in self.matches:
            choices = self.match_choices[m["id"]]
            has_choice = any([choices["3"], choices["1"], choices["0"]])
            if has_choice:
                selected.append(m)
                total_choices += sum([choices["3"], choices["1"], choices["0"]])

        # 更新缓存
        self.selected_count_cache = len(selected)
        self.avg_choices_cache = total_choices / self.selected_count_cache if self.selected_count_cache > 0 else 0
        return selected

    def update_selection_stats(self):
        """实时更新选择统计"""
        # 优先使用缓存，缓存失效时重新计算
        if self.selected_count_cache == 0:
            self.get_selected_matches()  # 触发缓存更新

        selected_count = self.selected_count_cache
        # 计算组合数 C(n,9)
        combo_count = self.combination(selected_count, 9) if 9 <= selected_count <=14 else 0

        # 估算总注数
        total_bets = 0
        if combo_count > 0 and self.selected_count_cache > 0:
            total_bets = int(combo_count * (self.avg_choices_cache **9))

        self.selection_stats.set(f"已选择场次: {selected_count} | 可生成组合数: {combo_count} | 预计总注数: {total_bets}")

    def apply_url(self):
        """应用输入的链接并刷新数据"""
        try:
            loading = tk.Toplevel(self.root)
            loading.title("加载中")
            loading.geometry("300x120")
            loading.transient(self.root)
            loading.grab_set()

            x = self.root.winfo_x() + self.root.winfo_width() // 2 - 150
            y = self.root.winfo_y() + self.root.winfo_height() // 2 - 60
            loading.geometry(f"300x120+{x}+{y}")

            tk.Label(loading, text="正在应用链接并加载数据...", font=("SimHei", 11)).pack(pady=20)
            self.root.update_idletasks()

            self.matches = self._init_match_data()
            self.init_match_list()
            self.clear_all()

            loading.destroy()
            messagebox.showinfo("成功", "数据链接已应用并加载完成")
        except Exception as e:
            messagebox.showerror("失败", f"应用链接失败: {str(e)}")

    def generate_combinations(self):
        """生成所有9场组合并计算金额"""
        selected_matches = self.get_selected_matches()
        selected_count = len(selected_matches)

        if not (9 <= selected_count <= 14):
            messagebox.showinfo("提示", f"请选择9-14场比赛！当前已选择{selected_count}场")
            return

        self.generated_combinations = list(itertools.combinations(selected_matches, 9))
        self.display_combinations()

    def display_combinations(self):
        """显示所有组合及金额"""
        self.combo_text.config(state=tk.NORMAL)
        self.combo_text.delete(1.0, tk.END)

        total_bets = 0
        total_amount = 0

        for i, combo in enumerate(self.generated_combinations, 1):
            sorted_combo = sorted(combo, key=lambda x: x["id"])
            match_ids = [str(m["id"]) for m in sorted_combo]

            combo_bets = 1
            for match in sorted_combo:
                choices = self.match_choices[match["id"]]
                select_count = sum([choices["3"], choices["1"], choices["0"]])
                combo_bets *= select_count

            combo_amount = combo_bets * 2
            total_bets += combo_bets
            total_amount += combo_amount

            self.combo_text.insert(tk.END, f"组合 {i}: 场次 {', '.join(match_ids)} | 注数: {combo_bets} | 金额: {combo_amount}元\n")

            for match in sorted_combo:
                choices = self.match_choices[match["id"]]
                self.combo_text.insert(tk.END, f"  场次{match['id']}: {match['home']} vs {match['away']}\n")

                win_text = f"胜: {match['home']} (赔率: {match['odds3']})"
                draw_text = f"平: 平 (赔率: {match['odds1']})"
                lose_text = f"负: {match['away']} (赔率: {match['odds0']})"

                if choices["3"]:
                    win_text = f"胜: [{match['home']}] (赔率: {match['odds3']})"
                if choices["1"]:
                    draw_text = f"平: [平] (赔率: {match['odds1']})"
                if choices["0"]:
                    lose_text = f"负: [{match['away']}] (赔率: {match['odds0']})"

                self.combo_text.insert(tk.END, f"      {win_text}  |  {draw_text}  |  {lose_text}\n")

            self.combo_text.insert(tk.END, "\n")

        self.total_stats_var.set(f"总组合数: {len(self.generated_combinations)} | 总注数: {total_bets} | 总金额: {total_amount}元")
        self.combo_text.config(state=tk.DISABLED)

    def export_combinations(self):
        """导出组合结果到文本文件"""
        if not self.generated_combinations:
            messagebox.showinfo("提示", "请先生成组合！")
            return

        current_time = datetime.now().strftime("%Y%m%d_%H%M%S")
        default_filename = f"任9组合_{current_time}.txt"
        file_path = filedialog.asksaveasfilename(
            defaultextension=".txt",
            filetypes=[("文本文件", "*.txt"), ("所有文件", "*.*")],
            initialfile=default_filename
        )

        if not file_path:
            return

        try:
            with open(file_path, "w", encoding="utf-8") as f:
                f.write(f"胜负彩任9组合 - {self.issue_var.get()}\n")
                f.write(f"生成时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n")
                f.write(f"数据来源: {self.data_url.get()[:50]}...\n")
                f.write(f"{self.total_stats_var.get()}\n\n")

                for i, combo in enumerate(self.generated_combinations, 1):
                    sorted_combo = sorted(combo, key=lambda x: x["id"])
                    match_ids = [str(m["id"]) for m in sorted_combo]

                    combo_bets = 1
                    for match in sorted_combo:
                        choices = self.match_choices[match["id"]]
                        select_count = sum([choices["3"], choices["1"], choices["0"]])
                        combo_bets *= select_count

                    combo_amount = combo_bets * 2

                    f.write(f"组合 {i}: 场次 {', '.join(match_ids)} | 注数: {combo_bets} | 金额: {combo_amount}元\n")
                    f.write("=" * 100 + "\n")

                    for match in sorted_combo:
                        choices = self.match_choices[match["id"]]
                        f.write(f"场次{match['id']}: {match['home']} vs {match['away']}\n")

                        win_line = f"  [胜] {match['home']}\n      赔率: {match['odds3']}" if choices["3"] else f"  胜 {match['home']}\n      赔率: {match['odds3']}"
                        draw_line = f"  [平] 平\n      赔率: {match['odds1']}" if choices["1"] else f"  平 平\n      赔率: {match['odds1']}"
                        lose_line = f"  [负] {match['away']}\n      赔率: {match['odds0']}" if choices["0"] else f"  负 {match['away']}\n      赔率: {match['odds0']}"

                        f.write(f"{win_line}    {draw_line}    {lose_line}\n")
                        f.write("-" * 100 + "\n")
                    f.write("\n")

            messagebox.showinfo("成功", f"组合已导出到:\n{file_path}")
        except Exception as e:
            messagebox.showerror("错误", f"导出失败: {str(e)}")

    def export_combinations_as_images(self):
        """导出所有组合为图片文件"""
        if not self.generated_combinations:
            messagebox.showinfo("提示", "请先生成组合！")
            return

        save_dir = filedialog.askdirectory(title="选择保存图片的文件夹")
        if not save_dir:
            return

        current_time = datetime.now().strftime("%Y%m%d_%H%M%S")
        combo_dir = os.path.join(save_dir, f"任9组合图片_{current_time}")
        os.makedirs(combo_dir, exist_ok=True)

        try:
            # 尝试加载中文字体
            try:
                title_font = ImageFont.truetype("simhei.ttf", 22)
                subtitle_font = ImageFont.truetype("simhei.ttf", 18)
                normal_font = ImageFont.truetype("simhei.ttf", 16)
                small_font = ImageFont.truetype("simhei.ttf", 12)
                tiny_font = ImageFont.truetype("simhei.ttf", 10)
            except:
                title_font = ImageFont.load_default()
                subtitle_font = ImageFont.load_default()
                normal_font = ImageFont.load_default()
                small_font = ImageFont.load_default()
                tiny_font = ImageFont.load_default()

            for i, combo in enumerate(self.generated_combinations, 1):
                sorted_combo = sorted(combo, key=lambda x: x["id"])
                match_ids = [str(m["id"]) for m in sorted_combo]

                combo_bets = 1
                for match in sorted_combo:
                    choices = self.match_choices[match["id"]]
                    select_count = sum([choices["3"], choices["1"], choices["0"]])
                    combo_bets *= select_count
                combo_amount = combo_bets * 2

                img_height = 200 + len(sorted_combo) * 120
                image = Image.new('RGB', (1200, img_height), color='#f8f9fa')
                draw = ImageDraw.Draw(image)

                # 绘制标题区域
                draw.rectangle([(0, 0), (1200, 150)], fill='#e9ecef')
                draw.text((50, 40), f"胜负彩任9组合 - {self.issue_var.get()}", font=title_font, fill='#2d3436')
                draw.text((50, 80), f"组合 {i}: 场次 {', '.join(match_ids)} | 注数: {combo_bets} | 金额: {combo_amount}元",
                          font=subtitle_font, fill='#2d3436')
                draw.line([(50, 130), (1150, 130)], fill='#adb5bd', width=2)

                # 绘制每场比赛的详情
                y_position = 160
                for idx, match in enumerate(sorted_combo, 1):
                    bg_color = '#ffffff' if idx % 2 == 0 else '#f1f3f5'
                    draw.rectangle([(30, y_position), (1170, y_position + 100)], fill=bg_color)
                    draw.line([(30, y_position + 100), (1170, y_position + 100)], fill='#e9ecef', width=1)

                    match_header = f"场次{match['id']} [{match['league']}] {match['time']}"
                    draw.text((50, y_position + 10), match_header, font=normal_font, fill='#2d3436')

                    vs_text = f"{match['home']}  vs  {match['away']}"
                    draw.text((50, y_position + 40), vs_text, font=normal_font, fill='#2d3436')

                    # 选中样式
                    selected_bg = '#e74c3c'
                    selected_text_color = 'white'

                    # 1. 胜格子
                    win_rect = [(400, y_position + 15), (550, y_position + 90)]
                    win_bg = selected_bg if self.match_choices[match["id"]]["3"] else '#ffebee'
                    win_text = selected_text_color if self.match_choices[match["id"]]["3"] else '#e74c3c'
                    draw.rectangle(win_rect, fill=win_bg)
                    draw.rectangle(win_rect, outline='#dee2e6', width=2)

                    if self.match_choices[match["id"]]["3"]:
                        draw.text((420, y_position + 25), "✓", font=small_font, fill=win_text)

                    draw.text((475, y_position + 40), match["home"], font=small_font,
                              fill=win_text, anchor='mm')
                    draw.text((475, y_position + 70), f"赔率: {match['odds3']}", font=tiny_font,
                              fill=win_text, anchor='mm')

                    # 2. 平格子
                    draw_rect = [(570, y_position + 15), (680, y_position + 90)]
                    draw_bg = selected_bg if self.match_choices[match["id"]]["1"] else '#fff8e1'
                    draw_text = selected_text_color if self.match_choices[match["id"]]["1"] else '#f39c12'
                    draw.rectangle(draw_rect, fill=draw_bg)
                    draw.rectangle(draw_rect, outline='#dee2e6', width=2)

                    if self.match_choices[match["id"]]["1"]:
                        draw.text((590, y_position + 25), "✓", font=small_font, fill=draw_text)

                    draw.text((625, y_position + 40), "平", font=small_font,
                              fill=draw_text, anchor='mm')
                    draw.text((625, y_position + 70), f"赔率: {match['odds1']}", font=tiny_font,
                              fill=draw_text, anchor='mm')

                    # 3. 负格子
                    lose_rect = [(700, y_position + 15), (850, y_position + 90)]
                    lose_bg = selected_bg if self.match_choices[match["id"]]["0"] else '#e8f5e9'
                    lose_text = selected_text_color if self.match_choices[match["id"]]["0"] else '#27ae60'
                    draw.rectangle(lose_rect, fill=lose_bg)
                    draw.rectangle(lose_rect, outline='#dee2e6', width=2)

                    if self.match_choices[match["id"]]["0"]:
                        draw.text((720, y_position + 25), "✓", font=small_font, fill=lose_text)

                    draw.text((775, y_position + 40), match["away"], font=small_font,
                              fill=lose_text, anchor='mm')
                    draw.text((775, y_position + 70), f"赔率: {match['odds0']}", font=tiny_font,
                              fill=lose_text, anchor='mm')

                    y_position += 110

                # 绘制底部信息
                draw.line([(50, y_position + 20), (1150, y_position + 20)], fill='#adb5bd', width=1)
                draw.text((50, y_position + 40), f"生成时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}",
                          font=small_font, fill='#6c757d')

                img_path = os.path.join(combo_dir, f"组合_{i}.png")
                image.save(img_path)

            messagebox.showinfo("成功", f"所有组合图片已导出到:\n{combo_dir}")
        except Exception as e:
            messagebox.showerror("错误", f"导出图片失败: {str(e)}")

    def clear_all(self):
        """清空所有选择"""
        for match_id, choices in self.match_choices.items():
            # 重置选择状态
            for res in ["3", "1", "0"]:
                choices[res] = False

            # 重置UI样式（使用预存引用）
            for res in ["3", "1", "0"]:
                frame = choices["frames"][res]
                labels = choices["labels"][res]

                if res == "3":
                    frame.config(bg="#ffebee", relief=tk.RAISED)
                    for label in labels:
                        label.config(bg="#ffebee", fg="black")
                elif res == "1":
                    frame.config(bg="#fff8e1", relief=tk.RAISED)
                    for label in labels:
                        label.config(bg="#fff8e1", fg="black")
                else:
                    frame.config(bg="#e8f5e9", relief=tk.RAISED)
                    for label in labels:
                        label.config(bg="#e8f5e9", fg="black")

        # 重置缓存
        self.selected_count_cache = 0
        self.avg_choices_cache = 0

        self.generated_combinations = []
        self.combo_text.config(state=tk.NORMAL)
        self.combo_text.delete(1.0, tk.END)
        self.combo_text.config(state=tk.DISABLED)

        self.update_selection_stats()
        self.total_stats_var.set("总组合数: 0 | 总注数: 0 | 总金额: 0元")

    def refresh_data(self):
        """手动刷新比赛数据"""
        try:
            loading = tk.Toplevel(self.root)
            loading.title("加载中")
            loading.geometry("300x120")
            loading.transient(self.root)
            loading.grab_set()

            x = self.root.winfo_x() + self.root.winfo_width() // 2 - 150
            y = self.root.winfo_y() + self.root.winfo_height() // 2 - 60
            loading.geometry(f"300x120+{x}+{y}")

            tk.Label(loading, text="正在获取最新数据...", font=("SimHei", 11)).pack(pady=20)
            self.root.update_idletasks()

            self.matches = self._init_match_data()
            self.init_match_list()
            self.clear_all()

            loading.destroy()
            messagebox.showinfo("成功", "比赛数据已更新为最新")
        except Exception as e:
            messagebox.showerror("失败", f"刷新失败：{str(e)}")

    @staticmethod
    def combination(n, k):
        """计算组合数 C(n,k)"""
        if k < 0 or k > n:
            return 0
        if k == 0 or k == n:
            return 1
        k = min(k, n - k)
        result = 1
        for i in range(1, k + 1):
            result = result * (n - k + i) // i
        return result

if __name__ == "__main__":
    root = tk.Tk()
    try:
        # 设置默认字体确保中文显示正常
        default_font = font.nametofont("TkDefaultFont")
        default_font.configure(family="SimHei", size=10)
        root.option_add("*Font", default_font)
    except:
        pass  # 字体设置失败时使用默认字体

    app = Lottery9FromN(root)
    root.mainloop()
